#pragma once
#include <iostream>
#include <string>
#include <limits>
#include "../common/mysocket.hpp"
#include "../common/protocol.hpp"
#include "../common/logmessage.hpp"
#include "../common/nocopy.hpp"

class TcpClient: public NoCopy
{
    Socket _sockfd;
    std::string _svrip;
    uint16_t _svrport;

public:
    TcpClient(const std::string &ip, uint16_t port)
        : _svrip(ip), _svrport(port)
    {
        _sockfd.Create();
        _sockfd.Connect(ip, port);
    }

    void Run()
    {
        std::string inbuffer;
        bool quit = false;
        while (!quit)
        {
            // 1.获取需求
            Request req;
            std::cout << "plase enter#";
            std::cout.flush();
            std::cin >> req._l >> req._op >> req._r;
            if (std::cin.fail())
            {
                // fflush(stdin); //无效
                // std::cin.sync(); //无效
                // std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //无效
                char c;
                while ((c = getchar()) != '\n');
                std::cin.clear();
                std::cout << "非法输入！" << std::endl;
                continue;
            }
            // 2.序列化
            std::string reqstr = req.Serialize();
            std::string temp = reqstr;
            // 3.添加长度报头
            reqstr = Encode(reqstr);
            // 4.向服务端发送数据
            Send(_sockfd.Fd(), reqstr);

            while (true)
            {
                // 5.从服务端接收数据
                bool ret = Receive(_sockfd.Fd(), &inbuffer);
                if (!ret)
                {
                    quit = true;
                    break;
                }
                // std::cout << "get a message!" << std::endl;
                // 6.获取一个完成的报文
                std::string respstr = Decode(inbuffer);
                if (respstr.empty())
                    continue;
                // std::cout << "get a package!" << std::endl;
                // 7.反序列化
                Response resp;
                resp.Deserialize(respstr);
                // 8.输出结果
                // std::cout << "ret: " << resp._ret << std::endl;
                // std::cout << "code: " << resp._code << std::endl;
                std::string err;
                switch (resp._code)
                {
                case 1:
                    err = "除0错误";
                    break;
                case 2:
                    err = "模0错误";
                    break;
                case 3:
                    err = "非法操作";
                    break;
                default:
                    std::cout << temp << " = " << resp._ret << " [success]" << std::endl;
                    break;
                }
                if (!err.empty())
                    std::cerr << err << std::endl;
                break;
            }
        }
    }
};